package com.coderg.gmall.order.rabbitmq;

import com.coderg.gmall.model.enums.OrderStatus;
import com.coderg.gmall.order.config.RabbitConfig;
import com.coderg.gmall.order.service.OrderInfoService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @Description  通用的一个消息消费类
 * @Author CoderG
 * @Date 2025/6/13 22:29
 **/
@Component
@Slf4j
public class MessageConsumer {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    OrderInfoService orderInfoService;
    /**
     * 最大重试次数
     */
    private static final int MAX_RETRY_COUNT = 2;
    /**
     * 消费失败后延迟投递时间 单位毫秒
     */
    private static final int DELAY_TIME = 1000;

    @RabbitListener(queues = {RabbitConfig.BUSINESS_QUEUE,RabbitConfig.RETRY_QUEUE})
    public void handleMessage(Message message, Channel channel) throws IOException {
        try {
            // 1. 尝试处理消息
            processMessage(message);

            // 2. 处理成功，手动确认
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        } catch (Exception e) {
            log.error(e.getMessage());
            // 3. 处理失败逻辑
            handleFailedMessage(message, channel);
        }
    }

    private void processMessage(Message message){
        // 实际业务处理逻辑
        String orderId = new String(message.getBody());
        //调用超时取消订单接口
        orderInfoService.cancelOrder(Long.valueOf(orderId),
                OrderStatus.TIME_CANCEL.getComment());

    }

    private void handleFailedMessage(Message message, Channel channel) throws IOException {
        // 获取重试次数（从消息头或自定义属性）
        Integer retryCount = (Integer) message.getMessageProperties()
                .getHeaders()
                .getOrDefault("retry-count", 0);

        if (retryCount < MAX_RETRY_COUNT) {
            // 第一次失败，重新投递
            retryCount++;
            log.info("第" + retryCount + "次处理失败，准备重试...");

            // 设置重试次数
            message.getMessageProperties().getHeaders().put("retry-count", retryCount);

            // 延迟n秒后重新投递到重试队列
            rabbitTemplate.convertAndSend(
                    // 重试交换机
                    RabbitConfig.DLX_EXCHANGE,
                    //routingKey
                    RabbitConfig.RETRY_ROUTING_KEY,
                    message,
                    m -> {
                        //设置延迟投递时间
                        m.getMessageProperties().setDelay(DELAY_TIME);
                        return m;
                    });

            // 确认已从原队列移除（避免重复消费）
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        } else {
            // 达到最大重试次数，记录日志并放弃
            log.info("消息最终处理失败，放弃重试: " + new String(message.getBody()));

            // 可选：将失败消息转移到死信队列
            // rabbitTemplate.convertAndSend("dlx.exchange", "dlx.routing", message);

            // 确认已消费（不再重新投递）
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

            // 记录到数据库或日志系统
            logFailedMessage(message);
        }
    }

    private void logFailedMessage(Message message) {
        // 实现失败消息的持久化记录
        log.error("消息投递失败: " + new String(message.getBody()));
    }
}
